﻿using Core.Framework.Loger;
using Core.Framework.Model.WebSockets;
using Core.Framework.Redis;
using Core.Framework.Redis.Queue_Helper;
using Core.Framework.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core.Middleware.WebSockets
{
    public class QueueMsg
    {
        public bool DoDispatch(QueryMessage model)
        {
            var msg = this.StructureMsg(model);

            if (msg == null)
                return false;

            RunningLogerInfoModel logerInfo = new RunningLogerInfoModel { Message = model };

            // 获取所有客户机
            var redis = new RedisHelper();
            var keys = redis.HashKeys(RedisQueueHelperParameter.QueueService);

            Dictionary<string, List<Listener_Template>> dic
                = new Dictionary<string, List<Listener_Template>>();

            // 构造服务列表
            foreach (var item in keys)
                dic.Add(item, redis.HashGet<List<Listener_Template>>(RedisQueueHelperParameter.QueueService, item));

            Func<Listener_Template, bool> where = (a) => 
                (
                    WebSokcetHelper.WebSocketMidWare.Template.ToLower() == model.Template.ToLower() 
                    && a.Subscription != null 
                    && a.Subscription.Contains(model.MessageKey)
                )
                || 
                (
                    WebSokcetHelper.WebSocketMidWare.Template.ToLower() != model.Template.ToLower()
                    && 
                    a.Subscription == null
                );

            // 筛选出符合条件的客户端
            var clients = dic.Where(a => a.Value.Where(where).FirstOrDefault() != null).ToArray();

            if (clients != null && clients.Count() > 0)
            {
                logerInfo.IsPublish = true;
                if (model.MessageType == MessageTypeEnum.Single)
                {
                    // 随机分配一个 客户端 [需要优化]
                    var i = new Random().Next(0, clients.Count() - 1);
                    redis.Publish(clients[i].Key, msg.TryToJson());
                    logerInfo.clients.Add(clients[i].Key);
                }

                else if (model.MessageType == MessageTypeEnum.Group)
                    foreach (var item in clients)
                    {
                        redis.Publish(item.Key, msg.TryToJson());
                        logerInfo.clients.Add(item.Key);
                    }
            }
            else
            {
                if (
                    model.Template.ToLower() == WebSokcetHelper.WebSocketMidWare.Template.ToLower()
                    || model.RetryCount >= model.MaxRetryCount)
                {
                    logerInfo.IsPublish = true;

                    if (model.MessageType == MessageTypeEnum.Single)
                        RedisQueueHelper
                            .ListPush(RedisQueueHelperParameter.SingleNull, msg.TryToJson());

                    RedisQueueHelper.ListPush(
                        RedisQueueHelperParameter.History,
                        msg.TryToJson());
                }
            }


            if (!logerInfo.IsPublish)
            {
                model.RetryCount++;
                RedisQueueHelper.SortedPush(
                    RedisQueueHelperParameter.UntreatedQueue,
                    model.TryToJson(), 1000 * model.DelaySeconds);
            }

            RunningLoger.Add(logerInfo.TryToJson());

            return true;

        }

        private MessageQueue StructureMsg(QueryMessage model)
        {

            // 根据token 获取登陆信息
            var result
                = RedisQueueHelper.HashGet(RedisQueueHelperParameter.WebSocketByToken, model.ClientToken);

            // 判断是否登陆
            if (!string.IsNullOrWhiteSpace(result))
            {
                var client = ((string)result).TryToEntity<ClientInfo>();

                return new MessageQueue
                {
                    Template = model.Template,
                    ClientInfo = new ClientInfo
                    {
                        User = new UserInfo
                        {
                            Key = client.User.Key,
                            Parameter = client.User.Parameter
                        },
                        Project = new ProjectInfo
                        {
                            ProjectToken = client.Project.ProjectToken,
                            CallUrl = client.Project.CallUrl
                        }
                    },
                    Message = new Message
                    {
                        Content = model.Content,
                        MessageKey = model.MessageKey,
                        MessageType = model.MessageType,
                        Parameter = model.Parameter,
                        SendDateTime = model.SendDateTime
                    }
                };
            }

            return null;
        }
    }
}
